/***************************************************************************
 *   Copyright (C) 2006 by Sassan Panahinejad				   *
 *   ico2ico2@gmail.com							   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

/*
	This program is basically just there to test libloop, everything it does could
	also be done with losetup.
*/

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>

#include "loop.h"
#include "looptest.h"

#define LOOP_NAME "/dev/loop%d"
#define LOOP_NAME_SIZE (strlen(LOOP_NAME)+1)
int get_action(int argc, char *argv[]);
int main(int argc, char *argv[]);
void print_help();

int offset = 0, sizelimit = 0;
int main(int argc, char *argv[])
{
	char action, *loopfile, loopfile_new[LOOP_NAME_SIZE], *filename;
	int loopno = 0, ret;
	action = get_action(argc, argv);
	set_output_level(3);
	switch (action) {
		case 's':
			if (argc < 4) {
				printf("Too few options\n");
				print_help();
				exit(EXIT_FAILURE);
			}
			process_options(argc, argv);
			loopfile = argv[argc-2];
			filename = argv[argc-1];
			if (!strcmp(loopfile, "-")) {
				loopfile = find_unused_loop(LOOP_NAME);
				if (!loopfile) {
					printf("Cannot find unused loop device\n");
					return EXIT_FAILURE;	
				}
				printf("Using loop device %s\n", loopfile);	
			}
			ret = set_loop(loopfile, filename, offset, sizelimit);
			if (ret) 
				return EXIT_FAILURE;
			return loopno;
		case 'd':
			if (argc != 3) {
				printf("Incorrect number of arguments\n");
				print_help();
				exit(EXIT_FAILURE);
			}
			loopfile = argv[2];
			ret = del_loop(loopfile);
			if (ret) 
				return EXIT_FAILURE;
			return 0;
		case 'f':
			if (argc != 3) {
				printf("Incorrect number of arguments\n");
				print_help();
				exit(EXIT_FAILURE);
			}
			loopfile = argv[2];
			ret = loop_get_filename(loopfile, &filename);
			if (ret)
				return EXIT_FAILURE;
			printf("%s\n", filename);
			return 0;
		default:
			print_help();
			return 0;
	}
	print_help();	
	return 0;
}

int get_action(int argc, char *argv[])
{
        char action;
        static struct option actions[] = {
                {"set", 0, 0, 's'},
                {"delete", 0, 0, 'd'},
                {"file", 0, 0, 'f'},
                {0, 0, 0, 0}
        };
        if (argc <= 2) {
                printf("Too few arguments\n");
                print_help();
                exit(EXIT_FAILURE);
        }
        action = getopt_long(2, argv, "sdf", actions, NULL);
        return action;
}

/*
	Processes options from the command line.
	Arguments are those recieved by the main function.
	Returns 0 on success, <0 on failure.
*/
int process_options(int argc, char *argv[])
{
	int c, option_index;
	while (1) {
		static struct option long_options[] = {
			{"offset", 1, 0, 'o'},
			{"sizelimit", 1, 0, 'l'},
			{0, 0, 0, 0}
		};
		c = getopt_long (argc, argv, "o:l:", long_options, &option_index);
		if (c == -1)
			break;
		switch (c) {
			case 'o':
				offset = atoi(optarg);
				break;
			case 'l':
				sizelimit = atoi(optarg);
				break;
		
			default:
				return -2;
		}
	}
	return 0;
}

void print_help()
{
	printf(
		"looptest is a test application for libloop.\n"
		"Usage: looptest <operation> <device> [file]\n"
		"Operations:\n"
		"	--set, -s		Set up the loop device <dev> to point to <file>.\n"
		"	--delete, -d		Free up the loop device <dev>.\n"
		"	--file, -f		Find the filename associated with <dev>.\n\n"
		"If you wish looptest to find a free loop device, give - as the device name.\n\n"
	);
}
